modernize units (#969)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Mon, 2 Jan 2023 18:11:23 +0000 (11:11 -0700)
committerGitHub <noreply@github.com>
Mon, 2 Jan 2023 18:11:23 +0000 (11:11 -0700)
* modernize units

fmt_* returns a std::pair of the value and the units.
use structured binding to unpack the pair.
use scoped enumeration for the units system.

* make units formatter a class.

* cleanup unitsformatter instance.

kml.cc
kml.h
units.cc
units.h

diff --git a/kml.cc b/kml.cc
index 0b8536038451bba1a1338ee4e100da6629e7e39c..5fe7bea28eafd67460ae6cdd3e8050e315d9c127 100644 (file)
--- a/kml.cc
+++ b/kml.cc
@@ -39,6 +39,7 @@
 #include <QList>                       // for QList
 #include <QString>                     // for QString, QStringLiteral, operator+, operator!=
 #include <QStringList>                 // for QStringList
+#include <QStringLiteral>              // for qMakeStringPrivate, QStringLit...
 #include <QVector>                     // for QVector
 #include <QXmlStreamAttributes>        // for QXmlStreamAttributes
 #include <Qt>                          // for ISODate
@@ -53,7 +54,7 @@
 #include "src/core/logging.h"          // for Warning, Fatal
 #include "src/core/xmlstreamwriter.h"  // for XmlStreamWriter
 #include "src/core/xmltag.h"           // for xml_findfirst, xml_tag, fs_xml, xml_attribute, xml_findnext
-#include "units.h"                     // for fmt_setunits, fmt_speed, fmt_altitude, fmt_distance, units_aviation, units_metric, units_nautical, units_statute
+#include "units.h"                     // for UnitsFormatter, UnitsFormatter...
 #include "xmlgeneric.h"                // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
 
 
@@ -357,18 +358,19 @@ void KmlFormat::wr_init(const QString& fname)
     u = tolower(opt_units[0]);
   }
 
+  unitsformatter = new UnitsFormatter();
   switch (u) {
   case 's':
-    fmt_setunits(units_statute);
+    unitsformatter->setunits(UnitsFormatter::units_t::statute);
     break;
   case 'm':
-    fmt_setunits(units_metric);
+    unitsformatter->setunits(UnitsFormatter::units_t::metric);
     break;
   case 'n':
-    fmt_setunits(units_nautical);
+    unitsformatter->setunits(UnitsFormatter::units_t::nautical);
     break;
   case 'a':
-    fmt_setunits(units_aviation);
+    unitsformatter->setunits(UnitsFormatter::units_t::aviation);
     break;
   default:
     fatal("Units argument '%s' should be 's' for statute units, 'm' for metric, 'n' for nautical or 'a' for aviation.\n", opt_units);
@@ -404,6 +406,8 @@ void KmlFormat::wr_deinit()
   oqfile->close();
   delete oqfile;
   oqfile = nullptr;
+  delete unitsformatter;
+  unitsformatter = nullptr;
 
   if (!posnfilenametmp.isEmpty()) {
     // QFile::rename() can't replace an existing file, so do a QFile::remove()
@@ -572,34 +576,28 @@ void KmlFormat::kml_output_trkdescription(const route_head* header, const comput
   if (!header->rte_desc.isEmpty()) {
     kml_td(hwriter, QStringLiteral("Description"), QStringLiteral(" %1 ").arg(header->rte_desc));
   }
-  const char* distance_units;
-  double distance = fmt_distance(td->distance_meters, &distance_units);
+  auto [distance, distance_units] = unitsformatter->fmt_distance(td->distance_meters);
   kml_td(hwriter, QStringLiteral("Distance"), QStringLiteral(" %1 %2 ").arg(QString::number(distance, 'f', 1), distance_units));
   if (td->min_alt) {
-    const char* min_alt_units;
-    double min_alt = fmt_altitude(*td->min_alt, &min_alt_units);
+    auto [min_alt, min_alt_units] = unitsformatter->fmt_altitude(*td->min_alt);
     kml_td(hwriter, QStringLiteral("Min Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(min_alt, 'f', 3), min_alt_units));
   }
   if (td->max_alt) {
-    const char* max_alt_units;
-    double max_alt = fmt_altitude(*td->max_alt, &max_alt_units);
+    auto [max_alt, max_alt_units] = unitsformatter->fmt_altitude(*td->max_alt);
     kml_td(hwriter, QStringLiteral("Max Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(max_alt, 'f', 3), max_alt_units));
   }
   if (td->min_spd) {
-    const char* spd_units;
-    double spd = fmt_speed(*td->min_spd, &spd_units);
+    auto [spd, spd_units] = unitsformatter->fmt_speed(*td->min_spd);
     kml_td(hwriter, QStringLiteral("Min Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
   }
   if (td->max_spd) {
-    const char* spd_units;
-    double spd = fmt_speed(*td->max_spd, &spd_units);
+    auto [spd, spd_units] = unitsformatter->fmt_speed(*td->max_spd);
     kml_td(hwriter, QStringLiteral("Max Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
   }
   if (td->max_spd && td->start.isValid() && td->end.isValid()) {
     double elapsed = td->start.msecsTo(td->end)/1000.0;
     if (elapsed > 0.0) {
-      const char* spd_units;
-      double spd = fmt_speed(td->distance_meters / elapsed, &spd_units);
+      auto [spd, spd_units] = unitsformatter->fmt_speed(td->distance_meters / elapsed);
       if (spd > 1.0)  {
         kml_td(hwriter, QStringLiteral("Avg Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
       }
@@ -723,8 +721,6 @@ void KmlFormat::kml_output_positioning(bool tessellate) const
 /* Output something interesting when we can for route and trackpoints */
 void KmlFormat::kml_output_description(const Waypoint* pt) const
 {
-  const char* alt_units;
-
   if (!trackdata) {
     return;
   }
@@ -732,8 +728,6 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const
   QString hstring;
   gpsbabel::XmlStreamWriter hwriter(&hstring);
 
-  double alt = fmt_altitude(pt->altitude, &alt_units);
-
   writer->writeStartElement(QStringLiteral("description"));
   hwriter.writeCharacters(QStringLiteral("\n"));
   hwriter.writeStartElement(QStringLiteral("table"));
@@ -742,6 +736,7 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const
   kml_td(hwriter, QStringLiteral("Latitude: %1 ").arg(QString::number(pt->latitude, 'f', precision)));
 
   if (kml_altitude_known(pt)) {
+    auto [alt, alt_units] = unitsformatter->fmt_altitude(pt->altitude);
     kml_td(hwriter, QStringLiteral("Altitude: %1 %2 ").arg(QString::number(alt, 'f', 3), alt_units));
   }
 
@@ -763,14 +758,12 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const
   }
 
   if WAYPT_HAS(pt, depth) {
-    const char* depth_units;
-    double depth = fmt_distance(pt->depth, &depth_units);
+    auto [depth, depth_units] = unitsformatter->fmt_distance(pt->depth);
     kml_td(hwriter, QStringLiteral("Depth: %1 %2 ").arg(QString::number(depth, 'f', 1), depth_units));
   }
 
   if WAYPT_HAS(pt, speed) {
-    const char* spd_units;
-    double spd = fmt_speed(pt->speed, &spd_units);
+    auto [spd, spd_units] = unitsformatter->fmt_speed(pt->speed);
     kml_td(hwriter, QStringLiteral("Speed: %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
   }
 
diff --git a/kml.h b/kml.h
index 177e5df7353ce2da9b113c6570bdbbb6f5dd635e..4d9b922967daec209c255d8e69c80f95f6ff0ba7 100644 (file)
--- a/kml.h
+++ b/kml.h
@@ -34,6 +34,7 @@
 #include "src/core/datetime.h"          // for DateTime
 #include "src/core/file.h"              // for File
 #include "src/core/xmlstreamwriter.h"   // for XmlStreamWriter
+#include "units.h"                      // for UnitsFormatter
 #include "xmlgeneric.h"                 // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
 
 
@@ -226,6 +227,7 @@ private:
   QList<gpsbabel::DateTime>* gx_trk_times{nullptr};
   QList<std::tuple<int, double, double, double>>* gx_trk_coords{nullptr};
 
+  UnitsFormatter* unitsformatter{nullptr};
   gpsbabel::File* oqfile{nullptr};
   gpsbabel::XmlStreamWriter* writer{nullptr};
 
index aafdf90a6e2ce3c45c48138aa8932e66a0282bb6..74a51abe5efa78d062b6f7bf065b42c2a4232a20 100644 (file)
--- a/units.cc
+++ b/units.cc
 #include "defs.h"
 #include "units.h"
 
-static int units = units_statute;
 
-int
-fmt_setunits(fmt_units u)
+void
+UnitsFormatter::setunits(units_t u)
 {
   switch (u) {
-  case units_statute:
-  case units_metric:
-  case units_nautical:
-  case units_aviation:
+  case units_t::statute:
+  case units_t::metric:
+  case units_t::nautical:
+  case units_t::aviation:
     units = u;
-    return 0;
+    break;
   default:
-    return 1;
+    fatal("not done yet");
+    break;
   }
 }
 
-double
-fmt_distance(const double distance_meters, const char** tag)
+std::pair<double, QString>
+UnitsFormatter::fmt_distance(const double distance_meters) const
 {
   double d;
+  const char* tag;
 
   switch (units) {
-  case units_statute:
+  case units_t::statute:
     d = METERS_TO_FEET(distance_meters);
     if (d < 5280) {
-      *tag = "ft";
+      tag = "ft";
     } else  {
       d = METERS_TO_MILES(distance_meters);
-      *tag = "mi";
+      tag = "mi";
     }
     break;
-  case units_nautical:
-  case units_aviation:
+  case units_t::nautical:
+  case units_t::aviation:
     d = METERS_TO_NMILES(distance_meters);
-    *tag = "NM";
+    tag = "NM";
     break;
-  case units_metric:
+  case units_t::metric:
     d = distance_meters;
     if (d < 1000) {
-      *tag = "meters";
+      tag = "meters";
     } else {
       d = d / 1000.0;
-      *tag = "km";
+      tag = "km";
     }
     break;
 
@@ -74,27 +75,28 @@ fmt_distance(const double distance_meters, const char** tag)
     break;
   }
 
-  return d;
+  return {d, tag};
 }
 
-double
-fmt_altitude(const double distance_meters, const char** tag)
+std::pair<double, QString>
+UnitsFormatter::fmt_altitude(const double distance_meters) const
 {
   double d;
+  const char* tag;
 
   switch (units) {
-  case units_statute:
-  case units_aviation:
+  case units_t::statute:
+  case units_t::aviation:
     d = METERS_TO_FEET(distance_meters);
-    *tag = "ft";
+    tag = "ft";
     break;
-  case units_nautical:
+  case units_t::nautical:
     d = METERS_TO_NMILES(distance_meters);
-    *tag = "NM";
+    tag = "NM";
     break;
-  case units_metric:
+  case units_t::metric:
     d = distance_meters;
-    *tag = "meters";
+    tag = "meters";
     break;
 
   default:
@@ -102,35 +104,36 @@ fmt_altitude(const double distance_meters, const char** tag)
     break;
   }
 
-  return d;
+  return {d, tag};
 }
 
-double
-fmt_speed(const double distance_meters_sec, const char** tag)
+std::pair<double, QString>
+UnitsFormatter::fmt_speed(const double speed_meters_per_sec) const
 {
   double d;
+  const char* tag;
 
   switch (units) {
-  case units_statute:
-    d = METERS_TO_MILES(distance_meters_sec) * SECONDS_PER_HOUR ;
-    *tag = "mph";
+  case units_t::statute:
+    d = METERS_TO_MILES(speed_meters_per_sec) * SECONDS_PER_HOUR ;
+    tag = "mph";
     break;
-  case units_nautical:
-  case units_aviation:
-    d = METERS_TO_NMILES(distance_meters_sec) * SECONDS_PER_HOUR ;
-    *tag = "knts";
+  case units_t::nautical:
+  case units_t::aviation:
+    d = METERS_TO_NMILES(speed_meters_per_sec) * SECONDS_PER_HOUR ;
+    tag = "knts";
     break;
-  case units_metric:
-    d = distance_meters_sec * SECONDS_PER_HOUR;
-    *tag = "meters/hour";
+  case units_t::metric:
+    d = speed_meters_per_sec * SECONDS_PER_HOUR;
+    tag = "meters/hour";
     if (d > 1000.0) {
       d /= 1000.0;
-      *tag = "km/hour";
+      tag = "km/hour";
     }
     break;
   default:
     fatal("not done yet");
 
   }
-  return d;
+  return {d, tag};
 }
diff --git a/units.h b/units.h
index fec3ff673cdf1ae76f7bd1842c6ca6bf843fda99..61c72a9e782e58deed687ba9520c771d4f634905 100644 (file)
--- a/units.h
+++ b/units.h
 #ifndef GPSBABEL_UNITS_H
 #define GPSBABEL_UNITS_H
 
-/*
- *  From units.c
- */
-enum fmt_units {
-  units_unknown = 0,
-  units_statute = 1,
-  units_metric = 2,
-  units_nautical =3,
-  units_aviation =4
-};
+#include <utility>  // for pair
+
+#include <QString>  // for QString
 
-int    fmt_setunits(fmt_units);
 
-double fmt_distance(double, const char** tag);
+class UnitsFormatter
+{
+public:
 
-double fmt_altitude(double, const char** tag);
+  /* Types */
 
-double fmt_speed(double, const char** tag);
+  enum class units_t {
+    statute,
+    metric,
+    nautical,
+    aviation
+  };
 
-#include "defs.h"
+  /* Member Functions */
 
+  void setunits(units_t u);
+  std::pair<double, QString> fmt_distance(double distance_meters) const;
+  std::pair<double, QString> fmt_altitude(double distance_meters) const;
+  std::pair<double, QString> fmt_speed(double speed_meters_per_sec) const;
+
+  /* Data Members */
+
+  units_t units{units_t::statute};
+
+};
 #endif //GPSBABEL_UNITS_H